/**  
 * All rights Reserved, Designed By http://www.pete-cat.com/
 * @Title:  UuidWorkPool.java   
 * @Package com.petecat.ruleengine.core.uuid   
 * @Description:TODO(用一句话描述该文件做什么)   
 * @author: 成都皮特猫科技     
 * @date:2017年12月10日 上午12:37:09   
 * @version V1.0 
 * @Copyright: 2017 www.pete-cat.com Inc. All rights reserved. 
 * 注意：本内容仅限于成都皮特猫信息技术有限公司内部传阅，禁止外泄以及用于其他的商业目
 */  
package com.petecat.ruleengine.core.uuid;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import com.petecat.ruleengine.core.redis.SystemRedisTemplate;
import com.petecat.ruleengine.core.util.IdWorker;

import redis.clients.util.MurmurHash;

/**   
 * @ClassName:  UuidWorkComp   
 * @Description:uuid工作组件  
 * @author: admin
 * @date:   2017年12月10日 上午12:37:09   
 */
@Component
public class UuidWorkComp implements ApplicationListener<EmbeddedServletContainerInitializedEvent>{
	
	private Log log = LogFactory.getLog(getClass());

	@Value("${work_datacenter}")
	private int datacenter;
	
	@Value("${work_number}")
	private int workNumber;
	
	@Value("${sys_name}")
	private String sysName;
	@Autowired
	private SystemRedisTemplate systemRedisTemplate;
	private ArrayList<WorkThread> workThreads = null;
	public WorkThread getIdWorker(){
		int pos = Math.abs(MurmurHash.hash(String.valueOf(Thread.currentThread().getId()+ThreadLocalRandom.current().nextInt(workThreads.size())).getBytes(),12345678)%workThreads.size());
		return workThreads.get(pos);
	}
	
	
	/**   
	 * <p>Title: onApplicationEvent</p>   
	 * <p>Description: </p>   
	 * @param event   
	 * @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)   
	 */  
	@Override
	public void onApplicationEvent(EmbeddedServletContainerInitializedEvent event) {
		try {
			if(workNumber<=0) {
				throw new BeanCreationException("workNumber not less then one");
			}
			workThreads = new ArrayList<>(workNumber);
			TomcatEmbeddedServletContainer container = (TomcatEmbeddedServletContainer) event.getEmbeddedServletContainer();
			//端口号
			int port = container.getPort();
			InetAddress address = InetAddress.getLocalHost();
			String ip = address.getHostAddress();
			String ipPort = ip+":"+port;
			String currentTimeKey = datacenter+"_"+sysName+"_work_size";
            //检查当前机器工作线程是否足够
			List<Long> works = this.systemRedisTemplate.hGetListObject(ipPort, sysName, Long.class);
			List<Long> needWorks = new ArrayList<>();
			int remainSize = 0;
			if(CollectionUtils.isEmpty(works)) {
				remainSize = workNumber;
			}else{
				if(works.size()>workNumber) {
					 needWorks.addAll(works.subList(0, workNumber));
				}else{
					needWorks.addAll(works);
					remainSize = workNumber - works.size();
				}
			}
			if(remainSize>0) {
				long data =this.systemRedisTemplate.incByStep(currentTimeKey, remainSize);
				for(int i=0;i<remainSize;i++) {
					needWorks.add(data-i);
				}
			}
			if( works==null || needWorks.size()>works.size() ) {
				this.systemRedisTemplate.hSetListObject(ipPort, sysName, needWorks);
			}
			//开始产生工作线程
			for(long workId : needWorks) {
				WorkThread workThread = new WorkThread();
				IdWorker worker = new IdWorker(workId,datacenter);
				workThread.setIdWorker(worker);
				workThreads.add(workThread);
			}
		} catch (Exception e) {
			throw new BeanCreationException("UuidWorkComp onApplicationEvent",e);
		}
		
	}
   
}